/*
 *	softTimer
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

typedef unsigned int u32;
typedef unsigned char u8;

typedef void*(*SOFT_TIMER_FUNC)(void*);
typedef unsigned char TIMER_HANDLE;
typedef struct __SOFT_TIMER{
	unsigned int count;
	unsigned int load;
	char state;
	char mode;
	SOFT_TIMER_FUNC	hook;
	TIMER_HANDLE handle;
}SOFT_TIMER;

enum SOFTTIMER_MODE {
	MODE_SINGLE	= 0x00,
	MODE_AUTOLOAD	= 0x01
};

#define TIMER_STATE_INIT	0x01
#define TIMER_STATE_PAUSE	0x10

#define SOFTARRAYSIZE		16

/*******************************************************************************/
static SOFT_TIMER SoftTimerArray[SOFTARRAYSIZE];

void softtimer_init(void)
{
	memset(&SoftTimerArray, 0, sizeof(SoftTimerArray));
}

char setTimer(u32 t, enum SOFTTIMER_MODE m, void *f)
{
	char index,state;
	SOFT_TIMER *pst;
	
	for(index = 0; index < SOFTARRAYSIZE; index++)
	{
		pst = &SoftTimerArray[index];
		if(!(pst->state & TIMER_STATE_INIT))
		{
			if(t == 0) return -2;
			pst->state |= TIMER_STATE_INIT;
			pst->count = pst->load = t;
			pst->mode = m;
			pst->hook = (SOFT_TIMER_FUNC)f;
			pst->handle = index;
			break;
		}
	}
	
	return index == SOFTARRAYSIZE ? -1 : pst->handle;
}

char delTimer(TIMER_HANDLE h)
{
	if(h < 0 || h > SOFTARRAYSIZE) return -1;
	if(!(SoftTimerArray[h].state & TIMER_STATE_INIT)) return -2;
	SoftTimerArray[h].state &= ~TIMER_STATE_INIT;
	return 0;
}

char pauseTimer(TIMER_HANDLE h)
{
	if(h < 0 || h > SOFTARRAYSIZE) return -1;
	if(!(SoftTimerArray[h].state & TIMER_STATE_INIT)) return -2;
	if((SoftTimerArray[h].state & TIMER_STATE_PAUSE)) return -3;
	SoftTimerArray[h].state |= TIMER_STATE_PAUSE;
	return 0;
}

char resumeTimer(TIMER_HANDLE h)
{
	if(h < 0 || h > SOFTARRAYSIZE) return -1;
	if(!(SoftTimerArray[h].state & TIMER_STATE_INIT)) return -2;
	if(!(SoftTimerArray[h].state & TIMER_STATE_PAUSE)) return -3;
	SoftTimerArray[h].state &= ~TIMER_STATE_PAUSE;
	return 0;
}

char reloadTimer(TIMER_HANDLE h, unsigned int n, enum SOFTTIMER_MODE m)
{
	if(h < 0 || h > SOFTARRAYSIZE) return -1;
	if(!(SoftTimerArray[h].state & TIMER_STATE_INIT)) return -2;
	SoftTimerArray[h].load = SoftTimerArray[h].count = n ? n : SoftTimerArray[h].load;
	SoftTimerArray[h].mode = m;
	return 0;
}

void activeTimer(void)
{
	char index;
	SOFT_TIMER *pst;
	
	for(index = 0; index < SOFTARRAYSIZE; index++)
	{
		pst = &SoftTimerArray[index];
		if((pst->state & TIMER_STATE_INIT) && !(pst->state & TIMER_STATE_PAUSE))
		{
			pst->count--;
			if(!pst->count)
			{
				if(pst->hook) pst->hook(NULL);
				if(pst->mode & MODE_AUTOLOAD)
				{
					pst->count = pst->load;
				}
				else
				{
					pst->state &= ~TIMER_STATE_INIT;
				}
			}
		}
	}
}



/*******************************************************************************/
/*
 * test 
 */
void delay(int t)
{
	volatile int time;
	for(time = 0; time < t; time++);
}

void* func1(void* v)
{
	printf("1\r\n");
	return NULL;
}
void* func2(void* v)
{
	pauseTimer(0);
	return NULL;
}
void* func3(void* v)
{
	resumeTimer(0);
	return NULL;
}
void* func4(void* v)
{
	reloadTimer(0, 2, MODE_AUTOLOAD);
	return NULL;
}
#define TIME1MS		(500000)
void main(void)
{
	softtimer_init();
	
	setTimer(1, MODE_AUTOLOAD, func1);
	setTimer(2, MODE_SINGLE, func2);
	setTimer(3, MODE_AUTOLOAD, func3);
	setTimer(5, MODE_SINGLE, func4);
	while(1)
	{
		delay(TIME1MS * 1000);
		activeTimer();
		printf("----\r\n");
	}
}
